<?php
/**
 *
 * @file Session.php
 *
 *
 * New BSD License
 * \n
 * Copyright (c) 2010 Rpd-Team
 *
 * @namespace  rpd
 * @since      0.0.9
 */

/**
 * Manages sessions via database
 *
 * @since  0.0.9
 *
 * Instance this class before you do any output or start other sessions.
 * It will override the storage of sessions to the database.
 *
 * Therefor it uses the default connection which is in the registry as
 * "db/std" or you give other setting within the constructor like in
 * Db::__construct().
 *
 * @warning Before you use this class ensure you got the following table
 * within your database
 *
 * @code
 * CREATE TABLE session (
 * 	idsession VARCHAR(128) PRIMARY KEY,
 * 	data BLOB,
 * 	ip TEXT,
 * 	useragent TEXT,
 * 	updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP
 * )
 * @endcode
 *
 * @section Changelog
 *
 * <table>
 * 	<tr>
 * 		<th>Version</th>
 * 		<th>Description</th>
 *  </tr>
 *  <tr><td></td><td></td></tr>
 * </table>
 *
 * @section Examples
 *
 * @subsection Session-instance Manage session via database
 *
 * <pre>/bootstrap.php</pre>
 * @code
 * <?php
 *
 * new Session();		// this is enough to let rpd manage sessions
 *
 * // you can set and get variables as usual
 * $_SESSION["foo"] = "bar";
 * echo $_SESSION["some"]["other_variable"];
 *
 * ?>
 * @endcode
 *
 * @subsection Session-other-table Use another tablename
 *
 * <pre>/bootstrap.php</pre>
 * @code
 * <?php
 *
 * // use "foo" as the tablename to store sessions
 * new Session(NULL, "foo");	// NULL forces the "db/std" configuration
 *
 * ?>
 * @endcode
 *
 * @see Db::__construct()
 *
 */
class Session extends Db
{
	private $_table;

	public function __construct($settings = NULL, $table = "session")
	{
		parent::__construct($settings);

		session_set_save_handler(array($this,'open'),
		                         array($this,'close'),
		                         array($this,'read'),
		                         array($this,'write'),
		                         array($this,'destroy'),
		                         array($this,'garbagecollection'));

		$this->_table = $table;

		session_start();
	}

	public function open()
	{
		return true;
	}

	public function close()
	{
		return true;
	}

	public function read($session_id)
	{
		$result = $this->query("SELECT data
		                        FROM " . $this->_table . "
		                        WHERE idsession = '%s'
		                           && ip = '%s'
		                           && useragent = '%s'",
		                       $session_id,
		                       $_SERVER["REMOTE_ADDR"],
		                       $_SERVER["HTTP_USER_AGENT"]);

		if ($result->rowCount() == 1)
		{
			return $result->current("data");
		}

		return "";
	}

	public function write($sessionid, $data)
	{
		$this->query("REPLACE INTO `" . $this->_table . "`
		              (idsession, data, ip, useragent)
		              VALUES ('%s', '%s', '%s', '%s')",
		             $sessionid,
		             $data,
		             $_SERVER["REMOTE_ADDR"],
		             $_SERVER["HTTP_USER_AGENT"],
		             $sessionid);
	}

	public function destroy($sessionid)
	{
		return $this->query("DELETE FROM `" . $this->_table . "`
		                     WHERE `id` = '%s'",
		                    $sessionid);
	}

	public function garbagecollection($maxlifetime)
	{
		return $this->query("DELETE FROM `" . $this->_table . "`
		                     WHERE UNIX_TIMESTAMP(`updated`) < %s",
		                    time()-$maxlifetime);
	}
}

?>